part of YFree;

extension YPage_Net on YPage {
  void yPost<T extends dynamic>(String jkid, Map? kv, Function(bool isSuccess, List<T>? results, String code, String message) yAjaxCallback, {Function(dynamic map)? onModel, showProgress = true, showErrorToast = true, cacheEnable = false}) async {
    if (cacheEnable) {
      var cacheResult = await yRead(yGetPostCacheKey(jkid, kv));
      if (cacheResult != null) {
        Map<dynamic, dynamic> result = json.decode(cacheResult);
        _doYPostResult(jkid, kv, result, yAjaxCallback, onModel, showProgress, showErrorToast, cacheEnable, true);
        _doYPost(jkid, kv, yAjaxCallback, onModel, false, showErrorToast, true);
        return;
      }
    }
    _doYPost(jkid, kv, yAjaxCallback, onModel, showProgress, showErrorToast, cacheEnable);
  }

  void _doYPost<T extends dynamic>(String jkid, Map? kv, Function(bool isSuccess, List<T>? results, String code, String message) yAjaxCallback, Function(dynamic map)? onModel, bool showProgress, bool showErrorToast, bool cacheEnable) async {
    Map<dynamic, dynamic> result;
    try {
      result = await _post(jkid, kv, showProgress, showErrorToast);
    } catch (e) {
      if (showErrorToast) yToast(e.toString());
      yAjaxCallback(false, null, "y_999", e.toString());
      return;
    }
    _doYPostResult(jkid, kv, result, yAjaxCallback, onModel, showProgress, showErrorToast, cacheEnable, false);
  }

  Future<Map<dynamic, dynamic>> _post(String jkid, Map? kv, bool showProgress, bool showErrorToast) async {
    final dio = Dio();
    if (!yIsWeb) dio.options.connectTimeout = Duration(milliseconds: YConfig.timeOut);
    dio.options.receiveTimeout = Duration(milliseconds: YConfig.timeOut);
    dio.options.sendTimeout = Duration(milliseconds: YConfig.timeOut);
    dio.options.headers.addAll(await YConfig.onHttpHeader());
    dio.options.contentType = "application/x-www-form-urlencoded";
    if (!yIsWeb) {
      // (dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate = (client) {
      //   client.badCertificateCallback = (cert, host, port) => true;
      //   if (YConfig.httpProxy != "") client.findProxy = (uri) => "PROXY ${YConfig.httpProxy}";
      //   return null;
      // };
      if(YConfig.httpProxy.isNotEmpty)
      dio.httpClientAdapter = IOHttpClientAdapter()
        ..onHttpClientCreate = (client) {
          client.badCertificateCallback = (cert, host, port) => true;
          client.findProxy = (uri) => 'PROXY ${YConfig.httpProxy}';
          return client;
        };
    }
    try {
      yLog("$jkid:request:${kv == null || kv.isEmpty ? "无入参" : yToJson(kv)}");
      if (showProgress) yShowProgress();
      Map<String, dynamic> data = {"jkid": jkid, "jkparam": yToJson(kv ?? {})};
      data.addAll(await YConfig.onHttpParam());
      var response = await dio.post(YConfig.IP, queryParameters: data);
      if (showProgress) yDismissProgress();
      if (response.statusCode != 200) {
        yLog("$jkid:responseFailure:网络请求异常！！！\tErrorNo:${response.statusCode}\tMsg:${response.statusMessage!}");
        if (showErrorToast) yToast(YConfig.DEBUG ? "网络请求异常！！！\nErrorNo:${response.statusCode}\nMsg:${response.statusMessage!}" : "网络请求错误，请重试");
        return {"code": response.statusCode, "results": null, "message": response.statusMessage};
      }
      yLog("$jkid:responseSuccess:${yToJson(response.data)}");
      try {
        final resMap = response.data;
        final root = resMap["root"];
        if (root["code"] == "200") {
          return {"code": root["code"], "results": root["result"], "message": root["message"]};
        } else if (root["code"] == "-1001") {
          return {"code": root["code"], "results": root["result"], "message": root["message"]};
        } else {
          if (showErrorToast) yToast(YConfig.DEBUG ? "网络请求回执message：\n${root["message"]}" : root["message"]);
          return {"code": root["code"], "results": null, "message": root["message"]};
        }
      } on Exception {
        final msg = YConfig.DEBUG ? "网络请求回执message解析异常，响应字符串：\n${response.data}" : "网络请求错误，请重试";
        if (showErrorToast) yToast(msg);
        return {"code": "", "results": null, "message": msg};
      }
    } on Exception catch (e) {
      if (showProgress) yDismissProgress();
      yLog("$jkid:responseFailure:网络请求异常！！！\tErrorNo:\tMsg:$e");
      if (showErrorToast) yToast(YConfig.DEBUG ? "网络请求异常！！！\nErrorNo:\nMsg:$e" : "网络请求错误，请重试");
      return {"code": "", "results": null, "message": e.toString()};
    }
  }

  void _doYPostResult<T extends dynamic>(String jkid, Map? kv, Map<dynamic, dynamic> result, Function(bool isSuccess, List<T>? results, String code, String message) yAjaxCallback, Function(dynamic map)? onModel, bool showProgress, bool showErrorToast, bool cacheEnable, bool isFromCache) {
    switch (result["code"]) {
      case "200":
        var isBadData = false;
        List<dynamic> results = [];
        try {
          results = yIsWeb || yIsPC ? result["results"] : json.decode(result["results"]);
          List<T> values;
          if (onModel == null) {
            values = results as List<T>;
          } else {
            values = results.map((m) => onModel(m) as T).toList();
          }
          try {
            if (yIsAlive) yAjaxCallback(true, values, result["code"], result["message"]);
          } catch (e) {
            isBadData = true;
            if (showErrorToast) yToast(e.toString());
          }
        } catch (e) {
          isBadData = true;
          if (showErrorToast) yToast(e.toString());
          if (yIsAlive) yAjaxCallback(false, null, "y_999", e.toString());
        }
        if (cacheEnable && results.isNotEmpty && !isBadData) {
          if (!isFromCache) ySave(yGetPostCacheKey(jkid, kv), json.encode(result));
        } else {
          yDelete(yGetPostCacheKey(jkid, kv));
        }
        break;
      default:
        if (result["code"] == YConfig.yPostCommomErrorCode) {
          yDelete(yGetPostCacheKey(jkid, kv));
          YConfig.onYPostCommonError.call(yPage, result["code"], result["message"], jkid, kv, (isSuccess, results, code, message) {
            yAjaxCallback(isSuccess, results?.map((e) => e as T).toList(), code, message);
          }, onModel, showProgress, showErrorToast, cacheEnable);
        } else {
          yDelete(yGetPostCacheKey(jkid, kv));
          if (yIsAlive) yAjaxCallback(false, null, result["code"], result["message"]);
        }
        break;
    }
  }

  String yGetPostCacheKey(String jkid, Map? kv) {
    return "ypost_${jkid}_${json.encode(kv)}";
  }

/*
    // 分页示例
    var _page = 1;
    List<Model> models = [];
    Future<void> loadData({isAdd = false}) async {
      _page = isAdd ? _page + 1 : 1;
      return yPost<Model>("", {
        "page": _page,
      }, (isSuccess, results, code, message) async {
        _page = isSuccess ? (isAdd ? (results.isEmpty ? _page - 1 : _page) : _page) : (isAdd ? _page - 1 : _page);
        if (isSuccess) {
          if (!isAdd) models.clear();
          setState(() => models.addAll(results));
        }
      }, onModel: (m) => Model.fromJson(m), showProgress: !isAdd);
    }
  */
}
